/**
 * @file HelpConfigManager.cpp
 *
 * @author Alejandro Dario Simi
 * @url http://www.daemonraco.com
 * @date 2011-12-03
 */

#include <HelpConfigManager.hpp>

#include <fstream>
#include <iostream>
#include <sstream>
#include <stdlib.h>
#include <string>
#include <sys/stat.h>
using namespace std;

#include <defines.h>
#include <Utils.hpp>

HelpConfigManager::HelpConfigManager(string config) {
	this->_config = Utils::CleanPath(config);
	struct stat confSt;
	if(!stat(this->_config.c_str(), &confSt) != 0) {
		///@todo
	}
	this->_isLoaded = false;
	this->_title = "";
	this->_icon = "";

	this->load();
}

HelpConfigManager::~HelpConfigManager() {
}

bool HelpConfigManager::addItem(const vector<string> &conf) {
	bool out = false;

	int confSize = conf.size();
	if(confSize == 3 || confSize == 4) {
		ItemInfo info;

		if(confSize == 4) {
			info.isChild = true;
			info.parent = conf[3];
		} else {
			info.isChild = false;
			info.parent = "";
		}
		info.hasChildren = false;
		info.name = conf[1];
		info.url = conf[2];

		this->_items[conf[1]] = info;

		out = true;
	}
	return out;
}

string HelpConfigManager::config() const {
	return this->_config;
}

int HelpConfigManager::expandConfigLine(const string line, vector<string> &lines) const {
	lines.clear();

	string piece;
	stringstream ss(line);
	while(getline(ss, piece, ':')) {
		lines.push_back(piece);
	}

	return lines.size();
}

string HelpConfigManager::icon() const {
	return this->_icon;
}

string HelpConfigManager::init() const {
	return this->_init;
}

bool HelpConfigManager::isLoaded() const {
	return this->_isLoaded;
}

const HelpConfigManager::ItemInfoMap &HelpConfigManager::items() const {
	return this->_items;
}

bool HelpConfigManager::load() {
	if(!this->isLoaded()) {
		string script = this->_config + "/help.conf";

		struct stat scriptStat;
		if(stat(script.c_str(), &scriptStat) == 0) {
			fstream fscript(script.c_str(), ios::in);
			if(fscript.is_open()) {
				char buffer[XADOS_CONF_MAX_LINE_SIZE];
				string line;
				vector<string> configStmt;
				int lineNumber = 0;

				while(!fscript.eof()) {
					lineNumber++;
					fscript.getline(buffer, sizeof(buffer));
					line = noCommentsConfigLine(buffer);
					if(expandConfigLine(line, configStmt)) {
						if(!this->loadConfigLine(configStmt)) {
							cerr << XADOS_PROGRAM": Line " << lineNumber << " ignored. Value: " << line << endl;
						}
					}
				}

				fscript.close();
				this->_isLoaded = true;
			} else {
				cerr << XADOS_PROGRAM << ": Unable to open configuration file '" << script << "'." << endl;
			}
		} else {
			cerr << XADOS_PROGRAM": File '" << script << "' seems to not exist." << endl;
		}

		for(ItemInfoMap::iterator i = this->_items.begin(); i != this->_items.end(); i++) {
			if(i->second.isChild) {
				if(this->_items.find(i->second.parent) != this->_items.end()) {
					this->_items[i->second.parent].hasChildren = true;
				} else {
					cerr << XADOS_PROGRAM": Parent item '" << i->second.parent << "' doesn't exist." << endl;
				}
			}
		}
	}

	return this->isLoaded();
}

bool HelpConfigManager::loadConfigLine(const vector<string> &conf) {
	bool out = false;

	if(conf.size()) {
		if(conf[0] == "AddItem") {
			out = this->addItem(conf);
		} else if(conf[0] == "Set") {
			out = this->set(conf);
		}
	}

	return out;
}

string HelpConfigManager::noCommentsConfigLine(const string line) const {
	string out = line;

	size_t pos = line.find("#");
	if(pos != string::npos) {
		out = line.substr(0, pos);
	}

	return out;
}

bool HelpConfigManager::set(const vector<string> &conf) {
	bool out = false;

	if(conf.size() > 1) {
		if(conf[1] == "Title") {
			out = this->setTitle(conf);
		} else if(conf[1] == "Icon") {
			out = this->setIcon(conf);
		} else if(conf[1] == "Init") {
			out = this->setInit(conf);
		}
	}

	return out;
}

bool HelpConfigManager::setIcon(const vector<string> &conf) {
	bool out = false;

	if(conf.size() == 3) {
		this->_icon = conf[2];
		struct stat iSt;
		if(stat(this->_icon.c_str(), &iSt) != 0) {
			this->_icon = this->config() + "/" + conf[2];
			if(stat(this->_icon.c_str(), &iSt) != 0) {
				cerr << XADOS_PROGRAM": Icon image '" << conf[2] << "' doesn't exist. Neither '" << this->_icon << "'"
						<< endl;
				this->_icon = "";
			} else {
				out = true;
			}
		} else {
			out = true;
		}
	}

	return out;
}

bool HelpConfigManager::setInit(const vector<string> &conf) {
	bool out = false;

	if(conf.size() == 3) {
		this->_init = conf[2];
		out = true;
	}

	return out;
}

bool HelpConfigManager::setTitle(const vector<string> &conf) {
	bool out = false;

	if(conf.size() == 3) {
		this->_title = conf[2];
		out = true;
	}

	return out;
}

string HelpConfigManager::title() const {
	return this->_title;
}
